package com.zbs.framework.security.filter;

import com.zbs.framework.common.handler.FrameworkBusinessRuntimeException;
import com.zbs.framework.common.utils.ResponseUtil;
import com.zbs.framework.common.utils.ResultUtil;
import com.zbs.framework.security.constant.SecurityConstants;
import com.zbs.framework.security.entity.LoginUserInfo;
import com.zbs.framework.security.entity.UrlResources;
import com.zbs.framework.security.utils.TokenManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.intercept.RunAsUserToken;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.FilterInvocation;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.security.sasl.AuthenticationException;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;

@Configuration
@Slf4j
public class DynamicSecurityRunAsManager implements ApplicationContextAware {

    public Authentication buildRunAs(String token, String sign, Authentication authentication, FilterInvocation fi) throws ServletException, IOException {
        if (!StringUtils.hasLength(token)) {
            return null;
        }
        // 公钥
//        System.out.println(sign);
        String privateSign = "";
        //从redis里获取用户登录信息
        LoginUserInfo securityUser;
        try {
            securityUser = TokenManager.getLoginUser(token);
        } catch (FrameworkBusinessRuntimeException e) {
            ResponseUtil.out(fi.getResponse(),fi.getRequest(), ResultUtil.error().message(e.getMessage()).code(e.getErrCode()));
            throw new AuthenticationException(e.getMessage(),e);
        }
        if (securityUser == null) {
            return null;
        }

        Collection<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("");
        if (!CollectionUtils.isEmpty(securityUser.getPermissions())) {
            securityUser.getPermissions().forEach(permissionValue -> {
                SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(permissionValue);
                authorities.add(simpleGrantedAuthority);
            });
        }

        // Add existing authorities
        return new RunAsUserToken(securityUser.getUsername(), securityUser,
                authentication.getCredentials(), authorities,
                authentication.getClass());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        RequestMappingHandlerMapping mapping = null;
        try {
            mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        } catch (BeansException e) {
            log.info("RequestMappingHandlerMapping not init，need spring boot web jar");
        }

        if (mapping != null) {
            // 获取url与类和方法的对应信息
            Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();

            map.forEach((k,v) -> {
                PreAuthorize annotation = v.getMethod().getAnnotation(PreAuthorize.class);
                if (k.getPathPatternsCondition() != null) {
                    k.getPathPatternsCondition().getPatterns().forEach(path ->{
                        if (annotation != null){
                            //操作
                            String value = annotation.value();
                            String authorize = value.substring(value.indexOf('(') + 1, value.lastIndexOf(')'));
                            String[] split = authorize.split(",");
                            Arrays.asList(split).forEach(s -> {
                                String permissionStr = s.substring(s.indexOf('\'') + 1, s.lastIndexOf('\''));
                                UrlResources urlResources = UrlResources.builder().path(path.getPatternString()).permission(permissionStr).build();
                                SecurityConstants.urlResources.add(urlResources);
                            });
                            SecurityConstants.pathIsAnnotations.put(path.getPatternString(),true);
                        }
                    });
                }
            });
        }
    }

}